package com.theten52.demo.io.s3;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Netty Demo
 *
 * @author wangjin
 * @date 2021/3/14
 */
public class NettyServer {

    public static void main(String[] args) throws Exception {
        NettyServer server = new NettyServer();

        server.start(8000);

    }

    public void start(int port) throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup();

        EventLoopGroup workerGroup = new NioEventLoopGroup();
        //通过nio方式来接收连接和处理连接
        try {
            ServerBootstrap b = new ServerBootstrap();
            //引导辅助程序

            b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                //设置nio类型的channel

                .childHandler(getHandler())
                .option(ChannelOption.SO_BACKLOG, 128)

                .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = b.bind(port).sync();
            //配置完成，开始绑定server，通过调用sync同步方法阻塞直到绑定成功

            f.channel().closeFuture().sync();
            //应用程序会一直等待，直到channel关闭

        } finally {
            workerGroup.shutdownGracefully();

            bossGroup.shutdownGracefully();//

            //这两个方法调用会等待线程池中的线程执行完毕后再退出

        }
    }

    private ChannelHandler getHandler() {
        return new ChannelInitializer<SocketChannel>() {
            ////有连接到达时会创建一个channel目的为acceptchannel的pipeline预添加的inboundhandler

            @Override

            public void initChannel(SocketChannel ch) throws Exception {

                // 在channel队列中添加一个handler来处理业务：注册两个OutboundHandler，执行顺序为注册顺序的逆序，
                // 所以应该是OutboundHandler2 OutboundHandler1

                ch.pipeline().addLast(new OutboundHandler1());

                ch.pipeline().addLast(new OutboundHandler2());

                // 注册两个InboundHandler，执行顺序为注册顺序，所以应该是InboundHandler1 InboundHandler2

                ch.pipeline().addLast(new InboundHandler1());

                ch.pipeline().addLast(new InboundHandler2());

            }

        };
    }
}
